#include <iostream>
#include <assert.h>
#include <string.h>

using namespace std;

namespace csd
{
    class string 
    {
    public:
        typedef char* iterator ;//迭代器
        typedef const char* const_iterator ;//迭代器
        
        iterator begin()
        {
            return _str;
        }

        iterator end()
        {
            return _str + _size;
        }

        const_iterator begin()const
        {
            return _str;
        }

        const_iterator end()const
        {
            return _str + _size;
        }

        string(const char* str = "")
        {
            if(str == NULL)
            {
                assert(false);
                return;
            }
            _size = strlen(str);
            _capacity = _size;
            _str = new char[_capacity+1];
            strcpy(_str,str);
        }
        
        //拷贝构造
        string(const string& str)
        {
            _str = NULL;
            string tmp(str._str);
            swap(_str,tmp._str);
            _size = tmp._size;
            _capacity = tmp._capacity;
        }
        
        //析构函数
        ~string()
        {
            delete[] _str;
            _str = NULL;
            _size = _capacity = 0;
        }

        //赋值重载
        string& operator= (string str)
        {
            swap(_str,str._str);
            _size = str._size;
            _capacity = str._capacity;
            return *this;
        }

        const char* c_str()const 
        {
            return _str; 
        }

        size_t size()const 
        {
            return _size;
        }

        size_t capacity()const 
        {
            return _capacity;
        }

        char& operator[] (size_t pos)
        {
            assert(pos < _size);
            return _str[pos];
        }

        const char& operator[] (size_t pos)const 
        {
            assert(pos < _size);
            return _str[pos];
        }

        void reserve(size_t n)
        {
            if(n > _capacity)
            {
                char* tmp = new char[n+1];
                strcpy(tmp,_str);
                delete[] _str;
                _str = tmp;
                _capacity = n;
            }
        }
        
        void push_back(char ch)
        {
            if(_size == _capacity)
            reserve(capacity() == 0 ? 4 : _capacity*2);

            _str[_size] = ch;
            _size++;
            _str[_size] = '\0';
        }

        string& operator+= (char ch)
        {
            push_back(ch);
            return *this;
        }

        void append(const char* str)
        {
            size_t len = strlen(str);
            if(_size + len > _capacity)
            reserve(_size + len);

            strcpy(_str+_size,str);
            _size += len;
        
        }
        
        string& operator+= (const char* str)
        {
            //重载+= 可以直接用append
            append(str);
            return *this;
        }

        string& insert(size_t pos,char ch)
        {
            assert( pos <= _size);
            if(_size == _capacity)
                reserve(_capacity == 0 ? 4 : _capacity*2);

            size_t end = _size + 1;
            while(end != pos)
            {
                _str[end] = _str[end-1];
                end--;
            }

            _str[pos] = ch;
            _size++;
            return *this;
        }

        string& insert(size_t pos,const char* str)
        {
            assert(pos <= _size);
            size_t len = strlen(str);
            if(_size + len > _capacity)
                reserve(_size + len);

            size_t end = _size + len;
            while(end != pos + len)
            {
                _str[end] = _str[end-len];
                end--;
            }
            
            strncpy(_str+pos,str,len);
            _size += len;
        }

        void erase(size_t pos,size_t len = npos)
        {
            assert(pos < _size);
            if(len == npos || pos + len >= _size)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else 
            {
                strcpy(_str + pos,_str + pos + len);
                _size -= len;
            }
        }

        void clear()
        {
            _str[0] = '\0';
            _size = 0;
        }

        size_t find(const char* sub,size_t pos)const 
        {
            assert(sub);
            assert(pos < _size);
            const char* pstr = strstr(_str+pos,sub);
            if(pstr == NULL)
            {
                return npos;
            }
            else 
            {
                return pstr - _str; 
            }
        }

        size_t find(char ch,size_t pos)
        {
            assert(pos < _size);
            for(int i = pos; i< _size;++i)
            {
                if(_str[i] == ch)
                     return i;
            }
            return npos;
        }

        string substr(size_t pos,size_t len = npos)
        {
            assert(pos < _size);
            size_t reallen = len;
            if(len == npos || pos + len >= _size)
            {
                reallen = _size - pos;
            }

            string sub;
            for(int i = 0;i<reallen;++i)
            {
                sub += _str[pos+i];
            }

            return sub;
        }

        void resize(size_t n,char ch = '\0')
        {
            if(n <= _size)
            {
                _str[n] = '\0';
                _size = n;
            }
            else 
            {
                reserve(n);
                for(int i = _size;i<n;++i)
                {
                    _str[_size] = ch;
                }
                _str[n] = '\0';
                _size = n;
            }

        }


    private:
         char* _str;
         size_t _size;
         size_t _capacity;
    public:
         static size_t npos;
    };

    size_t string::npos = -1;

    ostream& operator<< (ostream& out, string& str)
    {
        for(int i = 0;i<str.size();++i)
        {
            out << str[i];
        }

        return out;
    }

    istream& operator>> (istream& in, string& str)
    {
        str.clear();
        char ch;
        ch = in.get();
        const size_t N = 32;
        char buff[N];
        
        size_t i = 0;
        while(ch != ' '&& ch != '\n')
        {
            buff[i++] = ch;
            if(i == N-1)
            {
                buff[i] = '\0';
                str += buff;

                i = 0;
            }
            ch = in.get();
        }
        buff[i] = '\0';
        str += buff;

        return in;

    }

   void  test_string1()
    {
        csd::string s1("hello linux");
        csd::string s2;
        s2 = s1;

        csd::string::iterator it = s2.begin();
        while(it != s2.end())
        {
            cout << *it << " ";
            it++;
        }
       

    }

   void test_string2()
   {
       csd::string s1;
       cin >> s1;
       cout << s1;
   }
}

